/*
 Copyright (c) [Year] [name of copyright holder]
 [Software Name] is licensed under Mulan PSL v2.
 You can use this software according to the terms and conditions of the Mulan
 PSL v2.
 You may obtain a copy of Mulan PSL v2 at:
          http://license.coscl.org.cn/MulanPSL2
 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
 NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 See the Mulan PSL v2 for more details.
*/

#ifndef _1988WJ_PASTEADJUSTIMG_HPP_
#define _1988WJ_PASTEADJUSTIMG_HPP_

#include <fstream>
#include <opencv2/opencv.hpp>

/// @brief 用于图像调整和处理
class PasteAdjustImg {
  private:
    const cv::Mat &srcImg; // 源图像
    cv::Mat dstImg;        // 输出图像,未经任何调整时输出图像就是原图像
    cv::Mat tempImg;       // 临时图像
    std::string winName;   // 窗口名称

    int gridRows;         // 网格行数
    int gridCols;         // 网格列数
    int gridThickness;    // 网格线宽
    int gridLineType;     // 网格线类型
    cv::Scalar gridColor; // 网格线颜色
    // cv::Point gridPoint1; // 网格起始点
    // cv::Point gridPoint2; // 网格结束点

    // 校正图像的函数，用于调整图像的透视角度
    void CorrectImg();
    // 绘制网格
    void DrawGrid(cv::Point point1, cv::Point point2);

  public:
    /**
     * @brief 构造函数：初始化PasteAdjustImg对象
     *
     * 该构造函数用于通过指定的源图像、网格行数、网格列数、颜色、线条粗细、线条类型和窗口名称来初始化PasteAdjustImg对象。
     *
     * @param src 输入的源图像
     * @param rows 网格的行数
     * @param cols 网格的列数
     * @param color 绘制网格线的颜色
     * @param thickness 网格线的粗细
     * @param lineType 网格线的类型
     * @param windowName 显示图像的窗口名称，如果为空，则默认为"PasteAdjustImg"
     */
    PasteAdjustImg(const cv::Mat &src, const int rows = 1, const int cols = 1, const cv::Scalar &color = cv::Scalar(0, 0, 0),
                   const int thickness = 2, const int lineType = 8, const std::string &windowName = "PasteAdjustImg");

    /**
     * @brief 构造函数：初始化PasteAdjustImg对象
     *
     * 该构造函数用于通过指定的图像文件路径、网格行数、网格列数、颜色、线条粗细、线条类型和窗口名称来初始化PasteAdjustImg对象。
     *
     * @param path 图像文件的路径，不能为空
     * @param rows 网格的行数
     * @param cols 网格的列数
     * @param color 绘制网格线使用的颜色
     * @param thickness 网格线的粗细
     * @param lineType 网格线的类型
     * @param windowName 显示图像的窗口名称，如果为空，则默认为"PasteAdjustImg"
     */
    PasteAdjustImg(const std::string &path, const int rows = 1, const int cols = 1,
                   const cv::Scalar &color = cv::Scalar(0, 0, 0), const int thickness = 2, const int lineType = 8,
                   const std::string &windowName = "PasteAdjustImg");

    ~PasteAdjustImg();

    // 获取调整完成的目标图像
    cv::Mat GetDstImg() const;

    /**
     * @brief 在图像网格上绘制文本标签
     *
     * @param textList 包含要绘制的文本的字符串向量。每个字符串代表一行文本。
     * @param isTwoRows 指示文本是否应分布在两行。如果是true，则文本将被分成两行显示。
     * @param textColor 指定文本的颜色。使用cv::Scalar结构体，通常包含BGR值。
     * @param bgColor 指定文本背景区域的颜色。使用cv::Scalar结构体，通常包含BGR值。
     * @param fontFace 指定文本的字体。应使用OpenCV定义的字体常量。
     * @param thickness 指定文本线条的厚度。以像素为单位。
     * @param fontScale 指定文本的缩放比例。这是一个浮点数，表示文本的大小。
     */
    int DrawASKII(const std::vector<std::string> &textList, const bool isTwoRows = false,
                 const cv::Scalar &textColor = cv::Scalar(0, 0, 0), const cv::Scalar &bgColor = cv::Scalar(255, 255, 255),
                 const int fontFace = cv::FONT_HERSHEY_DUPLEX, const int thickness = 10, const double fontScale = 3.6);

    // 移除图像中的空白区域
    int RemoveBlank();

    // 修整图像边缘
    int TrimEdge();

    /**
     * @brief 更改或设置网格参数,此时并未在图像上实际绘制网格
     *
     * @param rows 网格的行数，必须大于等于 1 且小于原图像的行数
     * @param cols 网格的列数，必须大于等于 1 且小于原图像的列数
     * @param color 网格线的颜色，使用cv::Scalar结构体表示
     * @param thickness 网格线的宽度，非负整数
     * @param lineType 线型参数，线型必须是4, 8或cv::LINE_AA
     */
    void ChangeGrid(const int rows, const int cols, const cv::Scalar &color = cv::Scalar(0, 0, 0), const int thickness = 2,
                    const int lineType = 8);

    /**
     * @brief 保存当前处理的图像到指定路径。
     *
     * 该函数负责将当前处理后的图像（dstImg）保存到指定的文件路径。如果路径无效或保存失败，会抛出异常。
     *
     * @param path 图像保存的目标路径，不能为空。路径应为有效的文件路径，包括目录和文件名扩展名。
     */
    void SaveImg(const std::string &path);

    void SplitSaveImg(const std::vector<std::string> &fileNameList, const std::string &dir,
                      const std::string &extension = ".bmp");

    /**
     * @brief 该函数用于调整图像大小
     * 将源图像宽和高缩小到原来的一半(整体图像缩小到1/4)，然后保存到指定路径
     *
     * @param srcPath 图像源文件路径
     * @param destPath 调整大小后的图像保存路径
     */
    static void ImgResize(const std::string &srcPath, const std::string &destPath);
};
#endif